This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1"use client"; 2 3import { useEffect, useState } from "react"; 4import { useRouter, useParams } from "next/navigation"; 5import { getAccessToken } from "@/services/auth"; 6import { ApiClient } from "@/api-client/ApiClient"; 7import { UrlCard } from "@/components/UrlCard"; 8import type { GetCollectionPageResponse } from "@/api-client/types"; 9import { 10 Button, 11 Group, 12 Loader, 13 Stack, 14 Text, 15 Card, 16 Title, 17 Box, 18 SimpleGrid, 19} from "@mantine/core"; 20 21export default function CollectionPage() { 22 const [collection, setCollection] = 23 useState<GetCollectionPageResponse | null>(null); 24 const [loading, setLoading] = useState(true); 25 const [error, setError] = useState(""); 26 const router = useRouter(); 27 const params = useParams(); 28 const collectionId = params.collectionId as string; 29 30 // Create API client instance 31 const apiClient = new ApiClient( 32 process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:3000", 33 () => getAccessToken(), 34 ); 35 36 useEffect(() => { 37 const fetchCollection = async () => { 38 try { 39 setLoading(true); 40 const response = await apiClient.getCollectionPage(collectionId, { 41 limit: 50, 42 }); 43 setCollection(response); 44 } catch (error: any) { 45 console.error("Error fetching collection:", error); 46 setError(error.message || "Failed to load collection"); 47 } finally { 48 setLoading(false); 49 } 50 }; 51 52 if (collectionId) { 53 fetchCollection(); 54 } 55 }, [collectionId]); 56 57 if (loading) { 58 return <Loader />; 59 } 60 61 if (error || !collection) { 62 return ( 63 <Stack align="center"> 64 <Text c={"red"}>{error || "Collection not found"}</Text> 65 <Button onClick={() => router.back()}>Go Back</Button> 66 </Stack> 67 ); 68 } 69 70 return ( 71 <Box> 72 <Stack> 73 <Group justify="space-between"> 74 <Button variant="outline" onClick={() => router.back()}> 75 Back 76 </Button> 77 <Group> 78 <Button 79 variant="outline" 80 onClick={() => router.push(`/collections/${collectionId}/edit`)} 81 > 82 Edit Collection 83 </Button> 84 <Button onClick={() => router.push("/cards/add")}>Add Card</Button> 85 </Group> 86 </Group> 87 88 {/* Collection Header */} 89 <Card withBorder> 90 <Stack> 91 <Text fw={600} lineClamp={1}> 92 {collection.name} 93 </Text> 94 {collection.description && ( 95 <Text lineClamp={2}>{collection.description}</Text> 96 )} 97 </Stack> 98 99 <Group> 100 <Text fz={"sm"} c={"gray"}> 101 {collection.urlCards.length} cards 102 </Text> 103 <Text fz={"sm"} c={"gray"}> 104 By {collection.author.name} (@{collection.author.handle}) 105 </Text> 106 </Group> 107 </Card> 108 109 {/* Cards Section */} 110 <Stack> 111 <Group justify="space-between"> 112 <Title order={2}>Cards</Title> 113 {collection.pagination && collection.pagination.totalCount > 0 && ( 114 <Text fz={"sm"} c={"gray"}> 115 Showing {collection.urlCards.length} of{" "} 116 {collection.pagination.totalCount} cards 117 </Text> 118 )} 119 </Group> 120 121 {collection.urlCards.length > 0 ? ( 122 <Box> 123 <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing={"md"}> 124 {collection.urlCards.map((card) => ( 125 <UrlCard 126 key={card.id} 127 cardId={card.id} 128 url={card.url} 129 title={card.cardContent.title} 130 description={card.cardContent.description} 131 author={card.cardContent.author} 132 imageUrl={card.cardContent.thumbnailUrl} 133 addedAt={card.createdAt} 134 note={card.note?.text} 135 /> 136 ))} 137 </SimpleGrid> 138 139 {/* Pagination */} 140 {collection.pagination && collection.pagination.hasMore && ( 141 <Stack align="center"> 142 <Button variant="outline">Load More Cards</Button> 143 </Stack> 144 )} 145 </Box> 146 ) : ( 147 <Stack align="center"> 148 <Text c={"gray"}>No cards in this collection yet</Text> 149 <Button onClick={() => router.push("/cards/add")}> 150 Add Your First Card 151 </Button> 152 </Stack> 153 )} 154 </Stack> 155 </Stack> 156 </Box> 157 ); 158}